/**
 * Copyright (c) 2018-2028, Chill Zhuang 庄骞 (smallchill@163.com).
 * <p>
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * <p>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <p>
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.springblade.resource.service.impl;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.mongodb.BasicDBObject;
import com.mongodb.DBObject;
import com.mongodb.client.MongoDatabase;
import com.mongodb.client.gridfs.GridFSBucket;
import com.mongodb.client.gridfs.GridFSBuckets;
import com.mongodb.client.gridfs.GridFSDownloadStream;
import com.mongodb.client.gridfs.model.GridFSFile;
import org.bson.Document;
import org.springblade.core.mp.base.BaseServiceImpl;
import org.springblade.resource.entity.Attach;
import org.springblade.resource.mapper.AttachMapper;
import org.springblade.resource.service.IAttachService;
import org.springblade.resource.vo.AttachVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.gridfs.GridFsOperations;
import org.springframework.data.mongodb.gridfs.GridFsResource;
import org.springframework.data.mongodb.gridfs.GridFsTemplate;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.util.MultiValueMap;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URLEncoder;
import java.util.Map;

/**
 * 附件表 服务实现类
 * @author Blade
 * @since 2022-10-03
 */
@Service
public class AttachServiceImpl extends BaseServiceImpl<AttachMapper, Attach> implements IAttachService {

	@Autowired
	private GridFsTemplate gridFsTemplate;

	@Autowired
	private GridFsOperations gridFsOperations;

	@Override
	public IPage<AttachVO> selectAttachPage(IPage<AttachVO> page, AttachVO attach) {
		return page.setRecords(baseMapper.selectAttachPage(page, attach));
	}

	/**
	 * 上传文件
	 * @param file
	 * @return
	 */
	@Override
	public Attach putFile(MultipartFile file) {
		try {
			long fileSize = file.getSize();
			String originalFilename = file.getOriginalFilename();
			InputStream fileInputStream = file.getInputStream();

			// 上传前的基础校验 checkFile()
			// ...

			Attach attach = new Attach(
				null, null,
				originalFilename.substring(0, originalFilename.lastIndexOf(".")), originalFilename,
				originalFilename.substring(1 + originalFilename.lastIndexOf(".")),
				fileSize);

			if (this.save(attach)) {
				DBObject metaData = new BasicDBObject();
				metaData.put("attach", attach);
				gridFsTemplate.store(fileInputStream, String.valueOf(attach.getId()), file.getContentType(), metaData);

				String link = "/blade-resource/attach/endpoint/download/" + attach.getId();
				String domainUrl = "http://127.0.0.1:8089";
				attach.setLink(link);
				attach.setDomainUrl(domainUrl);
				this.updateById(attach);

				return attach;
			}
		} catch (IOException e) {
			throw new RuntimeException(e);
		}
		return null;
	}

	/**
	 * 下载文件
	 * @param id
	 * @return
	 */
	@Override
	public ResponseEntity<byte[]> downloadFile(String id) {
		GridFSFile gridFSFile = gridFsTemplate.findOne(new Query(Criteria.where("filename").is(id)));
		if (gridFSFile == null) {
			return null;
		}

		GridFsResource resource = gridFsOperations.getResource(gridFSFile);
		try {
			InputStream inputStream = resource.getInputStream();
			byte[] buffer = new byte[1024];

			ByteArrayOutputStream bos = new ByteArrayOutputStream();
			int i = 0;
			while (-1 != (i = inputStream.read(buffer))) {
				bos.write(buffer, 0, i);
			}
			buffer = bos.toByteArray();

			Document document = (Document) gridFSFile.getMetadata().get("attach");
			MultiValueMap responseHeaderMap = new HttpHeaders();

			String extension = (String) document.get("extension");
			if (extension.contains("png") || extension.contains("jpg") || extension.contains("jpeg")) {
				responseHeaderMap.add("content-type", "image/" + extension);
			} else {
				responseHeaderMap.add("content-type", "application/x-msdownload");
				responseHeaderMap.add("Content-Disposition",
					"attachment; filename=" + URLEncoder.encode((String) document.get("originalName"),
						"utf-8"));
			}

			ResponseEntity<byte[]> responseEntity = new ResponseEntity<>(buffer, responseHeaderMap, HttpStatus.OK);
			return responseEntity;
		} catch (Exception e) {
			e.printStackTrace();
		}

		return null;
	}

}
